<script setup lang="ts">
  import { computed, nextTick, ref, watch } from 'vue'
  import useDialogStore from '@/store/modules/dialog'
  import { useStyle, useDraggable } from './services'
  import HDialogLoading from './HDialogLoading.vue'
  import { Close } from '@element-plus/icons-vue'

  // contentPaddingBottom在设置了width才有效
  const props = defineProps({
    modelValue: {
      type: Boolean,
      default: () => false,
    },
    minWidth: Number,
    title: String,
    loading: Boolean,
    loadingText: String,
    width: Number,
    height: Number,
    contentPaddingTop: Number,
    contentPaddingLeft: Number,
    contentPaddingRight: Number,
    contentPaddingBottom: Number,
    isCloseBtnClickHideDialog: {
      type: Boolean,
      default: () => true,
    },
    isHideClose: {
      type: Boolean,
      default: () => false,
    },
  })

  const emits = defineEmits<{
    (e: 'update:modelValue', value: boolean): void
    (e: 'close'): void
  }>()

  const dialogStore = useDialogStore()
  const visible = ref(false)
  const hDialogHeaderRef = ref<HTMLElement | null>(null)
  const hDialogFooterRef = ref<HTMLElement | null>(null)
  const { transform, resetTransform, handleHDialogMousedown } = useDraggable()
  const { maskStyle, dialogStyle, hDialogContentStyle, setDialogStyle, resetDialogStyle } =
    useStyle()

  const onClose = () => {
    if (props.isCloseBtnClickHideDialog) {
      visible.value = false
      emits('update:modelValue', visible.value)
    }
    emits('close')
  }

  const gethDialogHeaderHeight = computed(() => {
    if (hDialogHeaderRef.value) {
      return hDialogHeaderRef.value.scrollHeight
    }
    return 0
  })

  const getHDialogFooterHeight = computed(() => {
    if (hDialogFooterRef.value) {
      return hDialogFooterRef.value.scrollHeight
    }
    return 0
  })

  const setHDialogContentStyle = () => {
    if (props.width || props.height) {
      hDialogContentStyle.value.maxHeight = `calc(100% - ${gethDialogHeaderHeight.value}px - ${getHDialogFooterHeight.value}px)`
      hDialogContentStyle.value.overflow = 'auto'
      hDialogContentStyle.value.boxSizing = 'border-box'
      hDialogContentStyle.value.paddingBottom = `${
        getHDialogFooterHeight.value ? 0 : props.contentPaddingBottom || 34
      }px`
    }

    hDialogContentStyle.value.paddingTop = `${props.contentPaddingTop || 24}px`
    hDialogContentStyle.value.paddingLeft = `${props.contentPaddingLeft || 34}px`
    hDialogContentStyle.value.paddingRight = `${props.contentPaddingRight || 34}px`
  }

  watch(
    props,
    (value) => {
      setDialogStyle({
        transform: transform.value,
        minWidth: props.minWidth,
        width: props.width,
        height: props.height,
      })
      visible.value = value.modelValue
      if (value.modelValue) {
        dialogStore.addZIndex()

        nextTick(() => {
          setHDialogContentStyle()
        })
        return
      }
      resetTransform()
      resetDialogStyle()
      dialogStore.minusZIndex()
    },
    { immediate: true, deep: true },
  )

  watch(
    transform,
    () => {
      setDialogStyle({ transform: transform.value })
    },
    { deep: true, immediate: true },
  )
</script>

<template>
  <teleport to="body">
    <transition name="h_dialog">
      <div v-if="visible" class="h_dialog_mask" :style="maskStyle">
        <div class="h_dialog_container" :style="dialogStyle">
          <header
            ref="hDialogHeaderRef"
            class="h_dialog_header"
            @mousedown="handleHDialogMousedown"
          >
            <div class="title">
              <i class="iconfont icon-dialog_title"></i>
              <slot name="title">
                <h3 class="text">{{ props.title || '' }}</h3>
              </slot>
            </div>
            <div v-if="!props.isHideClose" class="close" @click="onClose">
              <el-icon :size="16">
                <Close />
              </el-icon>
            </div>
          </header>
          <div v-if="$slots.default" class="h_dialog_content" :style="hDialogContentStyle">
            <slot></slot>
          </div>
          <footer v-if="$slots.footer" ref="hDialogFooterRef" class="h_dialog_footer">
            <slot name="footer"></slot>
          </footer>
          <HDialogLoading :loading="props.loading" :loading-text="props.loadingText" />
        </div>
      </div>
    </transition>
  </teleport>
</template>

<style scoped lang="scss">
  .h_dialog-enter-active,
  .h_dialog-leave-active {
    transition: opacity 0.4s ease;
  }

  .h_dialog-enter-from,
  .h_dialog-leave-to {
    opacity: 0;

    .h_dialog_container {
      transition: all 0.4s;
      top: -30px;
    }
  }

  .h_dialog-enter-to,
  .h_dialog-leave-from {
    .h_dialog_container {
      transition: all 0.4s;
      top: 0;
    }
  }
  .h_dialog_mask {
    position: fixed;
    top: 0;
    left: 0;
    width: 100vw;
    height: 100vh;
    z-index: 999;
    background-color: rgba($color: #000000, $alpha: 0.4);
    display: flex;

    .h_dialog_container {
      background-color: #fff;
      position: relative;
      margin: auto;

      .h_dialog_header {
        display: flex;
        justify-content: space-between;
        padding: 14px;
        box-shadow: 0 0 1px rgba($color: #000000, $alpha: 0.4) inset;
        cursor: move;

        .title {
          display: flex;
          align-items: center;
          gap: 4px;

          .iconfont {
            font-size: 15px;
            color: $primaryColor;
          }

          .text {
            font-family: '微软雅黑';
            font-size: 14px;
            line-height: 15px;
          }
        }

        .close {
          cursor: pointer;
          width: 16px;
          height: 16px;

          &:hover {
            color: $primaryColor;
          }
        }
      }

      .h_dialog_content {
        &::-webkit-scrollbar {
          display: none;
        }
      }

      .h_dialog_footer {
        display: flex;
        justify-content: center;
        padding: 30px 0;
        gap: 10px;
      }
    }
  }
</style>
